// 12.3.4 模板的模板实参
// 模板的模板实参（Template Template Arguments）是传递给模板模板参数的具体模板。这是C++模板系统中最高级的参数类型，允许将一个模板作为参数传递给另一个模板。

// 基本概念
// 模板的模板实参必须是一个类模板，其参数列表必须与模板模板参数的要求兼容：
// 声明一个接受模板模板参数的模板
template <
    typename T,
    template <typename> class Container>
class Stack
{
    Container<T> container;
    // ...
};

// 定义一个可用作模板模板实参的模板
template <typename T>
class Vector
{
    // ...
};

// 使用Vector作为模板模板实参
Stack<int, Vector> intStack;

// 模板模板实参的匹配规则
// 模板模板实参的匹配有特定规则：
// 1.C++17之前的精确匹配：
// 模板模板参数
template <template <typename X> class C>
class Example
{
};

// 模板模板实参
template <typename T>
class MyContainer
{
};

Example<MyContainer> e; // 正确：参数列表匹配

// 2.C++17的默认参数匹配：
// 带默认参数的模板
template <typename T, typename Alloc = std::allocator<T>>
class MyVector
{
};

// 模板模板参数
template <template <typename> class C>
class Example
{
};

// C++17前错误，C++17后正确
Example<MyVector> e;

// 使用标准库容器作为模板模板实参
// 在C++17之前，使用标准库容器作为模板模板实参很困难，因为它们通常有多个模板参数：
// C++17之前需要完全匹配参数列表
template <
    typename T,
    template <typename,
              typename Allocator = std::allocator<T>>
    class
    Container>
class Stack
{
    Container<T> container;
};

// 使用std::vector
Stack<int, std::vector> intStack;

// C++17简化了这一过程，允许忽略默认模板参数：
// C++17及之后
template <
    typename T,
    template <typename...> class Container>
class Stack
{
    Container<T> container;
};

// 可以使用任何标准容器
Stack<int, std::vector> vectorStack;
Stack<int, std::deque> dequeStack;
Stack<int, std::list> listStack;

// 模板模板实参的限制
// 模板模板实参有一些重要限制：
// 1.必须是类模板：
template <typename T>
T function(T); // 函数模板

template <template <typename> class T>
class Example
{
};

Example<function> error; // 错误：function不是类模板

// 2.参数列表兼容性：
// C++17之前：参数列表必须精确匹配
// C++17及之后：可以忽略默认参数，但参数种类和顺序必须兼容

// 3.不能是模板别名（C++14之前）：
template <typename T>
using MyVector = std::vector<T>;

// C++14之前不能用作模板模板实参

// 实际应用示例
// 模板模板参数在多种场景中非常有用：
template <
    typename T,
    template <typename...> class Container = std::vector>
class Stack
{
    Container<T> container;

public:
    void push(const T &value)
    {
        container.push_back(value);
    }

    T pop()
    {
        T value = container.back();
        container.pop_back();
        return value;
    }
};

// 使用不同容器
Stack<int> defaultStack;           // 使用std::vector
Stack<int, std::deque> dequeStack; // 使用std::deque

// 模板的模板实参是C++模板系统中最高级的特性之一，它提供了极高的灵活性和抽象能力，特别适用于需要在编译时选择不同容器或算法实现的场景。
